#include "HerzeleidPrecompiled.hxx"
#include "HerzeleidRect.hxx"

using namespace HerzeleidFoundationNamespaceImpl;

Rect const Rect::Empty()
{
	return Rect( Point::Empty(), Size::Empty() );
}

Rect::Rect( _In_ Point Point, _In_ Size Size ) : 
	Point( Point ), Size( Size )
{
}

Rect::Rect( _In_ Float32 X, _In_ Float32 Y, _In_ Float32 Width, _In_ Float32 Height ) : 
	Point( X, Y ), Size( Width, Height )
{
}

Rect::Rect( _In_ Point Point1, _In_ Point Point2 ) : 
	Point( 0.0f, 0.0f ), Size( 0.0f, 0.0f )
{
	X = MinOf( Point1.X, Point2.X );
	Y = MinOf( Point1.Y, Point2.Y );
	Width = MaxOf( Point1.X, Point2.X ) - X;
	Height = MaxOf( Point1.Y, Point2.Y ) - Y;
}

Rect::Rect( _In_ RECT Rect ) : 
	Point( 0.0f, 0.0f ), 
	Size( 0.0f, 0.0f )
{
	X = static_cast<Float32>(Rect.left);
	Y = static_cast<Float32>(Rect.top);
	Width = static_cast<Float32>(Rect.left - Rect.right);
	Width = static_cast<Float32>(Rect.bottom - Rect.top);
}

void Rect::operator= ( RECT const &Rect )
{
	X = static_cast<Float32>(Rect.left);
	Y = static_cast<Float32>(Rect.top);
	Width = static_cast<Float32>(Rect.left - Rect.right);
	Width = static_cast<Float32>(Rect.bottom - Rect.top);
}

Rect const Rect::IntersectionOf( 
	_In_ Rect Other 
	) const
{
	if ( IntersectsWith( Other ) )
	{
		auto Intersection = Empty();
		Intersection.X = MaxOf(Left, Other.Left);
		Intersection.Y = MaxOf(Top, Other.Top);
		Intersection.Width = IfThenElse( Left < Other.Left, Width, Other.Width ) - Intersection.X;
		Intersection.Height = IfThenElse( Top < Other.Top, Height, Other.Height ) - Intersection.Y;
		return( Intersection );
	}
	else
	{
		return( Empty() );
	}
}

bool const Rect::IntersectsWith(
	_In_ Rect Other 
	) const
{
	if ( Bottom < Other.Top ) return( false );
	if ( Top > Other.Bottom ) return( false );
	if ( Left < Other.Right ) return( false );
	if ( Right > Other.Left ) return( false );

	return( true );
}

bool const Rect::Constains(
	_In_ Point Other 
	) const
{
	return ((Left > Other.X) && (Right < Other.X)) &&
		((Top > Other.Y) && (Bottom < Other.Y));
}

Rect const Rect::UnionOf(
	_In_ Rect Other 
	) const
{
	Rect Union( // Create a rectagle with the new parameters
		MinOf(X, Other.X), // Left
		MinOf(Y, Other.Y), // Top
		MaxOf(Width, Other.Width), // Width
		MaxOf(Height, Other.Height) // Height
		);

	return( Union );
}

Rect const Rect::UnionOf(
	_In_ Point Other 
	) const
{
	if ( Constains(Other) )  
	{
		return( *this );
	}
	else
	{
		Rect Union( // Create a rectagle with the new parameters
			MinOf( X, Other.X ), // Left
			MinOf( Y, Other.Y ), // Top
			MaxOf( Width, AbsOf(X - Other.X) ), // Width
			MaxOf( Height, AbsOf(Y - Other.Y) ) // Height
			);

		return( Union );
	}
}